/*
 * logqueue.h
 *
 *  Created on: 2011-5-3
 *      Author: chenl
 */

#ifndef LOGQUEUE_H_
#define LOGQUEUE_H_

#include "common_bytequeue.h"
#include "common_err.h"
#include "common_util.h"
#include "common_libnamespace.h"
#include "logapi.h"

#include <assert.h>
#include <string.h>

CHENLIB_NAMESPACE_BEGIN

typedef int LogSource;

enum
{
	enmMaxLogSource = 64,
};

template<unsigned SOURCE_COUNT = enmMaxLogSource, unsigned CAPACITY = enmMaxLogLen>
class CLogQueue
{
public:
	CLogQueue()
	{}
	virtual ~CLogQueue()
	{}

	int32_t Initialize()
	{
		int32_t ret = S_OK;
		memset(arrLogPrefix_, 0, sizeof(arrLogPrefix_));
		for (unsigned i = 0; i < SOURCE_COUNT; ++i)
		{
			ret = byteQueue_[i].Initialize();
			if (0 > ret)
			{
				return ret;
			}
		}
		return ret;
	}

	int32_t Uninitialize()
	{
		int32_t ret = S_OK;
		for (unsigned i = 0; i < SOURCE_COUNT; ++i)
		{
			ret = byteQueue_[i].Uninitialize();
			if (0 > ret)
			{
				return ret;
			}
		}
		return ret;
	}
	//參數二 arrChLog不需要以'\0'結尾，參數三logLen為不包含'\0'的字符串長度
	int32_t Push(LogSource srcID, const char arrChLog[], unsigned logLen)
	{
		assert(NULL != arrChLog);
		if (unlikely(NULL == arrChLog))
		{
			return E_NULLPOINTER;
		}

		if (unlikely(srcID >= (int)SOURCE_COUNT))
		{
			return E_INVALIDARG;
		}

		if (unlikely(0 >= logLen || CAPACITY <= logLen))
		{
			return E_INVALIDARG;
		}

		BuffParam buff = {0};
		buff.pBuff = (uint8_t*)arrChLog;
		buff.len = logLen;
		return byteQueue_[srcID].Push(buff);
	}
	//參數二szLog為以'\0'結尾的字符串，參數三logLen為不包含'\0'的字符串長度
	int32_t Pop(LogSource srcID, char* szLog, unsigned& logLen)
	{
		if (unlikely(NULL == szLog))
		{
			return E_NULLPOINTER;
		}

		if (unlikely(srcID >= (int)SOURCE_COUNT))
		{
			return E_INVALIDARG;
		}

		if (unlikely(0 >= logLen))
		{
			return E_INVALIDARG;
		}

		BuffParam buff = {0};
		buff.pBuff = (uint8_t*)szLog;
		buff.len = logLen;
		int32_t ret = byteQueue_[srcID].Pop(buff);
		if (0 > ret)
		{
			return ret;
		}
		logLen = buff.len;
		buff.pBuff[logLen] = '\0';

		return ret;
	}

	unsigned Capacity() const
	{
		return CAPACITY;
	}
	unsigned SrcCount() const
	{
		return SOURCE_COUNT;
	}

	int32_t SetLogPrefix(LogSource logSource, char* szLogPrefix)
	{
		assert(NULL != szLogPrefix);
		if(unlikely(NULL == szLogPrefix))
		{
			return E_NULLPOINTER;
		}

		if (unlikely(0 > logSource || (int)SOURCE_COUNT <= logSource))
		{
			return E_INVALIDARG;
		}

		memcpy(arrLogPrefix_[logSource], szLogPrefix, sizeof(arrLogPrefix_[logSource]));
		return S_OK;
	}

	char* GetLogPrefix(LogSource logSource)
	{
		if (unlikely(0 > logSource || (int)SOURCE_COUNT <= logSource))
		{
			return NULL;
		}
		return arrLogPrefix_[logSource];
	}

	void Clear(LogSource logSource)
	{
		if (unlikely(0 > logSource || SOURCE_COUNT <= logSource))
		{
			return E_INVALIDARG;
		}
		byteQueue_[logSource].Clear();
	}

	void ClearAll()
	{
		for (unsigned i = 0; i < CAPACITY; ++i)
		{
			byteQueue_[i].Clear();
		}
	}

private:
	char					arrLogPrefix_[SOURCE_COUNT][enmMaxLogPrefixLen];
	CByteQueue<CAPACITY> 	byteQueue_[SOURCE_COUNT];
};

CHENLIB_NAMESPACE_END

#endif /* LOGQUEUE_H_ */
